package com.woniu.zsd.recycle.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.woniu.zsd.common.util.RedisKey;
import com.woniu.zsd.recycle.dto.MaterialTypeTreeDto;
import com.woniu.zsd.recycle.model.MaterialType;
import com.woniu.zsd.recycle.mapper.MaterialTypeMapper;
import com.woniu.zsd.recycle.param.AddTypeParam;
import com.woniu.zsd.recycle.param.SelectTypeParam;
import com.woniu.zsd.recycle.service.MaterialTypeService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 彭于晏
 * @since 2025年02月18日
 */
@Service
public class MaterialTypeServiceImpl extends ServiceImpl<MaterialTypeMapper, MaterialType> implements MaterialTypeService {
    @Resource
    private MaterialTypeMapper materialTypeMapper;
    @Resource
    private RedisTemplate<String,Object> redisObjectTemplate;
    @Resource
    private RabbitTemplate rabbitTemplate;
    @Override
    public List<MaterialTypeTreeDto> selectMaterialTypeTree() throws Exception {
        //先判断缓存中是否存在数据
        if (redisObjectTemplate.hasKey(RedisKey.CACHE_TYPE_TREE())){
            return (List<MaterialTypeTreeDto>) redisObjectTemplate.opsForValue().get(RedisKey.CACHE_TYPE_TREE());
        }
        QueryWrapper<MaterialType> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_id",0);//查一级类别
        wrapper.ne("status",1);//查状态不是删除的
        List<MaterialType> materialTypes = materialTypeMapper.selectList(wrapper);
        ArrayList<MaterialTypeTreeDto> list = new ArrayList<>();
        //循环集合，将materialType转为dto
        for (MaterialType materialType : materialTypes) {
            MaterialTypeTreeDto materialTypeTreeDto = BeanUtil.toBean(materialType, MaterialTypeTreeDto.class);
            findChildren(materialTypeTreeDto);
            list.add(materialTypeTreeDto);
        }
        //将查询到的数据保存到缓存中
        if (list.size()>0){
            redisObjectTemplate.opsForValue().set(RedisKey.CACHE_TYPE_TREE(),list);
        }else {
            redisObjectTemplate.opsForValue().set(RedisKey.CACHE_TYPE_TREE(),list,30, TimeUnit.SECONDS);
        }
        return list;
    }

    @Override
    public void add(AddTypeParam param) throws Exception {
        //用redis前置删除
        QueryWrapper<MaterialType> wrapper = new QueryWrapper<>();
        wrapper.eq("type_name",param.getTypeName());
        wrapper.eq("status",1);
        MaterialType materialType = materialTypeMapper.selectOne(wrapper);
        if (materialType != null) {
            throw new Exception("类别名称重复");
        }
        MaterialType type = BeanUtil.toBean(param, MaterialType.class);
        type.setTypeSelf(0);
        if (param.getParentId() == 0){
            type.setStatus(0);//0启用1删除2禁用
        }else {
            MaterialType parentType = materialTypeMapper.selectById(param.getParentId());
            if (parentType == null||parentType.getStatus() == 1) {
                throw new Exception("父类别不存在");
            }
            if (parentType.getTypeSelf() == 0){
                parentType.setTypeSelf(1);
                materialTypeMapper.updateById(parentType);
            }
            type.setStatus(parentType.getStatus());
        }
        materialTypeMapper.insert(type);
        //将key保存至消息队列中，延迟删除
        rabbitTemplate.convertAndSend("","waiting_delete_cache_queue",RedisKey.CACHE_TYPE_TREE());
    }

    @Override
    public Page<MaterialType> selectType(SelectTypeParam param) throws Exception {
        //开启分页
        Page<MaterialType> materialTypePage = new Page<>(param.getPageNum(), param.getPageSize());
        QueryWrapper<MaterialType> wrapper = new QueryWrapper<>();
        if (!StringUtils.isEmpty(param.getParentTypeName())){
            wrapper.like("type_name",param.getTypeName());
        }
        if (param.getStatus()!=-1){
            wrapper.eq("status",param.getStatus());
        }
        Page<MaterialType> materialTypePage1 = materialTypeMapper.selectPage(materialTypePage, wrapper);

        return materialTypePage1;
    }

    @Override
    public void disable(Integer materialTypeId) throws Exception {
        MaterialType materialType = materialTypeMapper.selectById(materialTypeId);
        if (materialType==null)throw new Exception("类别信息不存在");
        if (materialType.getStatus() != 0)throw new Exception("该类别已被禁用或删除，禁用失败");
        materialType.setStatus(2);
        materialTypeMapper.updateById(materialType);
        //级联禁用
        disableChildren(materialTypeId);
    }

    @Override
    public void enable(Integer materialTypeId) throws Exception {
        MaterialType materialType = materialTypeMapper.selectById(materialTypeId);
        if (materialType==null)throw new Exception("类别信息不存在");
        if (materialType.getStatus()!=2)throw new Exception("该类别已被启用或删除，禁用失败");
        enableParent(materialTypeId);
    }

    @Override
    public void delete(Integer materialTypeId) throws Exception {
        MaterialType materialType = materialTypeMapper.selectById(materialTypeId);
        if (materialType==null)throw new Exception("类别信息不存在");
        if (materialType.getStatus()==1)throw new Exception("该类别已被删除，删除失败");
        materialType.setStatus(1);
        materialTypeMapper.updateById(materialType);
        deleteChildren(materialTypeId);
    }

    @Override
    public List<MaterialType> userSelectType() throws Exception {
        QueryWrapper<MaterialType> wrapper = new QueryWrapper<>();
        wrapper.eq("status",0);
        List<MaterialType> materialTypes = materialTypeMapper.selectList(wrapper);
        if (materialTypes == null){
            throw new Exception("没有可用的类别");
        }
        return materialTypes;
    }

    public void findChildren(MaterialTypeTreeDto materialTypeTreeDto)throws Exception{
        QueryWrapper<MaterialType> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_id",materialTypeTreeDto.getMaterialTypeId());
        wrapper.ne("status",1);//查状态不是删除的
        List<MaterialType> materialTypes = materialTypeMapper.selectList(wrapper);
        //又遍历转换成dto
        for (MaterialType materialType : materialTypes) {
            MaterialTypeTreeDto childrenDto = BeanUtil.toBean(materialType, MaterialTypeTreeDto.class);
            //判断是否为空,为空才new了加到dto里面的子集合中
            if (materialTypeTreeDto.getChildren() == null) {
                materialTypeTreeDto.setChildren(new ArrayList<MaterialTypeTreeDto>());
            }
            //不为空才能直接add
            materialTypeTreeDto.getChildren().add(childrenDto);
            //递归调用找子类别的类别
            findChildren(childrenDto);
        }
    }
    public void disableChildren(Integer parentId)throws Exception{
        //查未被删除的子类别
        QueryWrapper<MaterialType> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_id",parentId);
        wrapper.ne("status",1);
        List<MaterialType> childrenList =materialTypeMapper.selectList(wrapper);
        for (MaterialType child : childrenList) {
            child.setStatus(2);
            materialTypeMapper.updateById(child);
            disableChildren(child.getMaterialTypeId());
        }
    }
    public void enableParent(Integer materialTypeId)throws Exception{
        MaterialType materialType = materialTypeMapper.selectById(materialTypeId);
        materialType.setStatus(0);
        materialTypeMapper.updateById(materialType);
        if (materialType.getParentId()!=0){
            enableParent(materialType.getParentId());
        }
    }
    public void deleteChildren(Integer parentId)throws Exception{
        QueryWrapper<MaterialType> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_id",parentId);
        List<MaterialType> materialTypes = materialTypeMapper.selectList(wrapper);
        for (MaterialType materialType : materialTypes) {
            materialType.setStatus(1);
            materialTypeMapper.updateById(materialType);
            deleteChildren(materialType.getMaterialTypeId());
        }
    }
}
